using System;
using full_leaf_framework.Visual;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace touhou_bullet_rain;

public class Youkai {

    public Drawable selfDrawable;

    public string youkaiType;
    public string uuid;
    public Vector2 pos;
    public Vector2 posCorrectSwift;
    public Vector2 velocity = Vector2.Zero;

    public float moveStrength = 6500f;
    public float friction = 0;
    public float frictionRate = 0;

    public float angle = 0;

    public float hitPoints = 60;

    private Level level;

    private float walkDustColdDown = 0f;
    private const float walkDustColdDownMax = 0.2f;

    public Youkai(string uuid, string youkaiType, Vector2 pos, Vector2 velocity, float friction, Level level) {
        this.uuid = uuid;
        this.youkaiType = youkaiType;
        this.pos = pos;
        posCorrectSwift = Vector2.Zero;
        this.velocity = velocity;
        this.friction = friction;
        this.level = level;
        try {
            var sprite = new AnimatedSprite(GameManager.Content.Load<Texture2D>("Player/" + youkaiType));
            selfDrawable = new Drawable(sprite, pos, Vector2.Zero);
        }
        catch {
            selfDrawable = null;
        }
    }

    public void HandleServerRequest(string[] paramsList) {
        if (!(paramsList[0] == uuid)) { return; }
        try {
            posCorrectSwift = new Vector2(float.Parse(paramsList[1]),
                float.Parse(paramsList[2])) - pos;
            velocity = new Vector2(float.Parse(paramsList[3]),
                float.Parse(paramsList[4]));
            friction = float.Parse(paramsList[5]);
        }
        catch (Exception e) {
            Console.WriteLine("Error When Handle Request -> " + e);
        }
    }

    public void Update(GameTime gameTime) {
        // 摩擦力与坐标更新
        float currSpeed = velocity.Length() - friction * (float)gameTime.ElapsedGameTime.TotalSeconds;
        if (currSpeed < float.Epsilon) { currSpeed = 0; }
        if (velocity.Length() > float.Epsilon) { velocity.Normalize(); velocity *= currSpeed; }
        pos += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
        CorrectCurrPos(gameTime);
        selfDrawable.pos = pos;
        // 处理本地更新事务
        walkDustColdDown -= (float)gameTime.ElapsedGameTime.TotalSeconds;
        if (walkDustColdDown < float.Epsilon) { walkDustColdDown = 0.0f; }
        if (velocity.Length() > 1f && walkDustColdDown < float.Epsilon) {
            float walkAngle = Player.VectorToAngle(-velocity);
            level.particleController.Burst("walk_burst", pos, angleRange: new float[2]
            { walkAngle - MathF.PI / 24, walkAngle + MathF.PI / 24});
            walkDustColdDown = walkDustColdDownMax;
        }
        // 走动粒子效果
        selfDrawable.angle += (float)gameTime.ElapsedGameTime.TotalSeconds * MathF.PI / 3;
        // 自身缓慢旋转
    }

    private void CorrectCurrPos(GameTime gameTime) {
        // 平滑插值使得对象移动同步偏差量
        float distance = posCorrectSwift.Length();
        float approachVelocity = 30f + distance * 1.5f + distance * distance * 0.5f;
        approachVelocity *= (float)gameTime.ElapsedGameTime.TotalSeconds;
        if (distance <= approachVelocity) {
            pos += posCorrectSwift;
            posCorrectSwift = Vector2.Zero;
        }
        else {
            Vector2 currSwift = posCorrectSwift;
            currSwift.Normalize(); currSwift *= approachVelocity;
            pos += currSwift;
            posCorrectSwift -= currSwift;
        }
    }

    public void HandleBurstRequest(string[] burstArgus) {
        if (burstArgus[1] == "graze_burst") {
            level.particleController.Burst("walk_burst", pos, angleRange: new float[2]
            { 0, 2 * MathF.PI }, particleCount: 16,
            velocityRange: new float[2] { 20f, 350f });
        }
        else {
            level.particleController.Burst(burstArgus[1], pos);
        }
    }

    public void Draw(Camera camera) {
        if (selfDrawable is not null) {
            camera.insertObject(selfDrawable);
        }
    }

}